import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';

import 'package:ac/api/ac_urls.dart';
import 'package:ac/data/ac_device_tool.dart';
import 'package:ac/data/ac_user_manager.dart';
import 'package:ac/network/ac_http.dart';
import 'package:ac/network/ac_http_utils.dart';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';

/// 打点请求头key统一传参
class HBLogHeadersKey {
  static const String acData = "data";
  static const String acLogType = "log_type";
  static const String acSubtype = "subtype";
  static const String acBehavior = "behavior";
  static const String acDeviceId = "device-id";
  static const String acAndroidId = "android_id";
  static const String acUserId = "user_id";
  static const String acPkg = "pkg";
  static const String acChnId = "chn_id";
  static const String acVer = "ver";
  static const String acPlatform = "platform";
  static const String acModel = "model";
  static const String acPVer = "p_ver";
  static const String acLanId = "lan_id";
  static const String acSecId = "sec_id";
  static const String acUtmSource = "utm_source";
  static const String acAfAdgroupId = "af_adgroup_id";
  static const String acAfAdset = "af_adset";
  static const String acAfAdsetId = "af_adset_id";
  static const String acAfStatus = "af_status";
  static const String acAfAgency = "af_agency";
  static const String acAfChannel = "af_channel";
  static const String acAfCampaign = "campaign";
  static const String acAfCampaignId = "campaign_id";
  static const String acCountry = "country";
  static const String acSysLan = "sys_lan";
}

/// 打点中所有涉及到的页面KEY
class LogPages {
  // 启动页面
  static const String launchPage = 'launch';

  // 登录页面埋点
  static const String quickLoginPage = 'quicklogin';
  static const String appleLoginPage = 'applelogin';
  static const String termsPage = 'terms';
  static const String privacyPage = 'privacy';
  static const String loginSuccessPage = 'loginsuccess';

  // 主tab点击事件埋点（具体tab名称根据实际情况填写）
  static const String tab1Page = 'tab1';
  static const String tab2Page = 'tab2';
  static const String tab3Page = 'tab3';
  static const String tab4Page = 'tab4';

  // 内购埋点
  static const String purchasePage = 'purchase';
  static const String createOrderPage = 'createorder';

  // 我的埋点
  static const String editAvatarPage = 'editavatar';
  static const String logoutPage = 'logout';
  static const String deleteAccountPage = 'deleteaccount';
  static const String customerPage = 'customer';
  static const String chatPage = 'chat';
  static const String publishPage = 'publish';
  static const String postListPage = 'postList';
  static const String postDetailPage = 'postDetail';

  // 其他
  static const String follow = 'follow';
  static const String unFollow = 'unFollow';
  static const String reportPage = 'report';
  static const String blockPage = 'block';
  static const String unBlockPage = 'unBlock';
}


class AcCryptoUntil {
  static String hbToMd5(String data) {
    // 将输入的字符串转换为字节
    List<int> bytes = utf8.encode(data);

    // 计算并返回MD5散列值的16进制字符串表示形式
    return md5.convert(bytes).toString();
  }
}
class LogPvManger {
  LogPvManger._();

  static const String _event = 'event';
  static const String _tm = 'tm';
  static const String _page = 'page';
  static const String _subPage = 'subPage';
  static const String _terPage = 'terPage';
  static const String _broadcasterId = 'broadcasterId';
  static const String _duration = 'duration';

  static void stat({
    String? page,
    String? subPage,
    String? terPage,
    String? broadcasterId,
  }) {
    var map = <String, dynamic>{};
    // ⚠️page传入下方的埋点事件page值
    if (page != null) {
      map[_page] = page;
    }
    if (subPage != null) {
      map[_subPage] = subPage;
    }
    if (terPage != null) {
      map[_terPage] = terPage;
    }
    if (broadcasterId != null) {
      map[_broadcasterId] = broadcasterId;
    }
    map[_duration] = 0;
    map[_event] = 'pv';
    map[_tm] = DateTime.now().millisecondsSinceEpoch;

    if (kDebugMode) {
      log('$map', name: 'LogPvMgr');
    }
    LogManger().putLog(LogType.globalBehavior, map);
  }
}

/// 打点类型
enum LogType {
  globalBehavior('event', 'global_behavior', 'event'),
  clickEvent("event", "click", "event");

  final String logType;
  final String subType;
  final String behavior;

  const LogType(this.logType, this.subType, this.behavior);
}

// 打点管理
class LogManger {
  static final LogManger _instance = LogManger._internal();

  factory LogManger() {
    return _instance;
  }

  LogManger._internal();

  static const String tag = "LogManger"; // 日志标签
  static const int limitSize = 20; // 打点任务最多缓存长度
  static int _serialId = 0;
  static String launcherId = AcCryptoUntil.hbToMd5(
      '${DateTime.now().millisecondsSinceEpoch}${AcDeviceTool().foDeviceId}');
  final List<Map<String, dynamic>> cacheList = [];
  bool _isWaitingForSend = false; // 是否需要延迟上报

  /// 上报日志
  void putLog(LogType logType, Map<String, dynamic>? event) {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    cacheList.insert(0, itemData);
    sendDelayed();
  }

  /// 延时发送日志
  void sendDelayed() {
    if (_isWaitingForSend) {
      return;
    }
    _isWaitingForSend = true;
    Timer(const Duration(milliseconds: 2000), () {
      _isWaitingForSend = false;
      sendLog(false);
    });
  }

  /// 发日志打点
  void sendLog(bool forceUploadAll) {
    try {
      List<Map<String, dynamic>> sendList = [];
      if (cacheList.isEmpty) {
        return;
      } else if (cacheList.length >= limitSize && !forceUploadAll) {
        sendList.addAll(cacheList.sublist(0, limitSize));
        cacheList.removeRange(0, limitSize);
      } else {
        sendList.addAll(cacheList);
        cacheList.clear();
      }
      _doUpload(sendList, true);
    } catch (e) {
      if (kDebugMode) {
        print(e);
      }
    }
  }

  /// 立马发送日志
  void putLogRightNow(LogType logType, Map<String, dynamic>? event) {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    List<Map<String, dynamic>> list = [];
    list.add(itemData);

    _doUpload(list, false);
  }

  /// 执行上传
  Future<void> _doUpload(
      List<Map<String, dynamic>> sendList, bool isContinue) async {
    try {
      Dio dio = Dio();
      dio.options.baseUrl = AcUrls.logHost;

      var res = await dio.post(
        AcUrls.log,
        data: sendList,
        options: Options(
          headers: AcHttpRequest.header,
        ),
      );
      sendDelayed();
    } catch (e) {
      if (kDebugMode) {
        print(e);
      }
    }
  }

  Map<String, dynamic> _buildItemData(String logType, String subType,
      String behavior, Map<String, dynamic>? event) {
    String platform = '';
    String model = '';
    if (Platform.isAndroid) {
      platform = 'Android';
      model = AcDeviceTool().foAndroidDeviceInfo?.hardware ?? '';
    } else if (Platform.isIOS) {
      platform = 'iOS';
      model = AcDeviceTool().foIosDeviceInfo?.model ?? '';
    }
    Map<String, dynamic> itemData = {};
    itemData[HBLogHeadersKey.acData] = [event];
    itemData[HBLogHeadersKey.acLogType] = logType;
    itemData[HBLogHeadersKey.acSubtype] = subType;
    itemData[HBLogHeadersKey.acBehavior] = behavior;
    itemData[HBLogHeadersKey.acDeviceId] = AcDeviceTool().foDeviceId;
    itemData[HBLogHeadersKey.acUserId] = AcUserManager.userInfoModel?.userInfo.userId;
    itemData[HBLogHeadersKey.acPkg] =
        AcDeviceTool().packageInfo.packageName ?? '';
    itemData[HBLogHeadersKey.acChnId] = '';
    itemData[HBLogHeadersKey.acVer] =
        AcDeviceTool().packageInfo.version ?? '';
    itemData[HBLogHeadersKey.acPlatform] = platform;
    itemData[HBLogHeadersKey.acModel] = model;
    itemData[HBLogHeadersKey.acPVer] =
        AcDeviceTool().packageInfo.buildNumber ?? '';
    itemData[HBLogHeadersKey.acLanId] = launcherId;
    itemData[HBLogHeadersKey.acSecId] = _serialId++;
    itemData[HBLogHeadersKey.acSysLan] =
        AcDeviceTool().foLocalLanguageCode ?? '';
    itemData[HBLogHeadersKey.acCountry] =
        AcUserManager.userInfoModel?.userInfo.country ?? '';
    return itemData;
  }
}
